import type { Ref } from 'vue'
import type { BaseComponentProps, RowData } from '@/types'
import { isRef, unref } from 'vue'

/**
 * 分离对象中的属性值
 * @param obj - 包含键的对象。
 * @param keys - 要提取的属性数组。
 * @returns 返回一个数组，第一个元素为提取的对象，第二个元素是剩余属性的对象。
 */
export function separateValues<T extends RowData, K extends keyof T>(obj?: T, ...keys: K[]) {
  const extract: Partial<T> = {}
  const remains: Partial<T> = {}

  if (obj) {
    for (const key in obj as Record<K, any>) {
      if (keys.includes(key)) {
        extract[key] = obj[key]
      }
      else {
        remains[key] = obj[key]
      }
    }
  }

  return [extract, remains] as [Pick<T, K>, Omit<T, K>]
}

/**
 * 字段排序规则，未指定排序的字段放置最后，其他的则按照升序排列。
 */
export function sortCompare(a?: number, b?: number) {
  if (typeof a !== 'number') {
    return 1
  }
  else if (typeof b !== 'number') {
    return -1
  }
  return a - b
}

/**
 * 解析一个值，类型取决于 `value` 的类型。
 *
 * @param value - 要解析的值，可以是 `Ref` 类型、函数类型或其他类型。
 * @param form - 传递给函数的表单数据。
 * @returns 解析后的值，其类型取决于 `value` 的类型。
 *   - 如果 `value` 是 `Ref` 类型，则返回 `Ref` 内部的类型。
 *   - 如果 `value` 是函数类型，则返回函数的返回类型。
 *   - 否则，返回 `value` 的类型。
 */
export function resolveDynamicValue<T>(value: T, form?: RowData): T extends Ref<infer R> ? R : T extends (...args: any[]) => infer R ? R : T {
  const _value = unref(value)
  if (typeof _value === 'function') {
    return _value(form)
  }
  else {
    return _value as any
  }
}

/**
 * 将类名转换为字符串
 *
 * @param className - 类名，可以是字符串、数组或对象。
 * @returns 返回类名字符串。
 */
function toStrClass(className: BaseComponentProps['class']) {
  if (!className)
    return ''
  if (typeof className === 'string')
    return className
  if (Array.isArray(className))
    return className.filter(Boolean).join(' ')
  if (typeof className === 'object') {
    return Object.entries(className).reduce((prev, [key, value]) => {
      if (value) {
        prev += ` ${key}`
      }
      return prev
    }, '')
  }
}
/**
 * 合并多个类名
 *
 * @param classNames - 类名数组，可以包含字符串、数组或对象。
 * @returns 返回合并后的类名字符串。
 */
export function mergeClass(...classNames: (BaseComponentProps['class'] | undefined)[]) {
  if (!classNames)
    return ''
  return classNames.filter(Boolean).map(toStrClass).join(' ')
}

/**
 * 将驼峰命名转换为短横线命名
 *
 * @param str - 驼峰命名的字符串。
 * @returns 返回短横线命名的字符串。
 */
export function camelToKebab(str: string): string {
  return str.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase()
}

/**
 * 将样式对象转换为字符串
 *
 * @param style - 样式对象，可以是字符串或对象。
 * @returns 返回样式字符串。
 */
function toStrStyle(style: BaseComponentProps['style']) {
  if (!style)
    return ''
  if (typeof style === 'string')
    return style.endsWith(';') ? style : `${style};`
  if (typeof style === 'object') {
    return Object.entries(style).reduce((prev, [key, value]) => {
      prev += `${camelToKebab(key)}:${value};`
      return prev
    }, '')
  }
}

/**
 * 合并多个样式
 *
 * @param styles - 样式数组，可以包含字符串或对象。
 * @returns 返回合并后的样式字符串。
 */
export function mergeStyle(...styles: BaseComponentProps['style'][]) {
  if (!styles)
    return ''
  return styles.map(toStrStyle).join('')
}

export function resolveVisible<O extends Record<string, any>>(
  data?: boolean | Ref<boolean> | O,
  defaultValue?: boolean,
  objVisibleGetter: ((data: O) => undefined | boolean | Ref<boolean>) = (data: O) => data.visible,
) {
  if (typeof data === 'boolean') {
    return data
  }
  else if (isRef(data)) {
    return data.value
  }
  else if (typeof data === 'object') {
    const visible = objVisibleGetter(data)
    return unref(visible) ?? defaultValue
  }
  else {
    return defaultValue
  }
}

export function resolveBind(data?: any) {
  if (typeof data === 'object') {
    return data
  }
  return undefined
}
